import { PropsWithChildren, useRef } from 'react';
import { AutoFocusContext, ComponentFocusProps } from './context';
import { useMemoizedFn } from 'ahooks';

export type CommandFormAutoFocusProps = PropsWithChildren<{
  specifyChildren?: boolean;
  enableFocusMove?: boolean;
}>;

// 位于CommandFormAutoFocus内部的PickInputForFocus选择框，会在单选选项框选择后，跳到下一个元素选择框
// specifyChildren为false时，按组件渲染顺序进行自动跳转，且所有选择框均会参与此行为
// specifyChildren为true时，仅有具有focusID的PickInputForFocus选择框会参与行为，并且跳转顺序按focusID从小到大
// enableFocusMove为false时不进行自动跳转
export const CommandFormAutoFocus = ({
  children,
  specifyChildren = false,
  enableFocusMove = true,
}: CommandFormAutoFocusProps) => {
  const autoFocusMap = useRef<Map<number, ComponentFocusProps>>(new Map());

  const register = useMemoizedFn((id: number, props: ComponentFocusProps) => {
    if (!enableFocusMove) {
      return -1;
    }

    if (!specifyChildren) {
      const ids = Array.from(autoFocusMap.current.keys()).sort((a, b) => a - b);
      const current = ids.at(-1);

      const key = current == null ? 0 : current + 1;

      autoFocusMap.current.set(key, props);

      return key;
    } else {
      autoFocusMap.current.set(id, props);
      return id;
    }
  });

  const unregister = useMemoizedFn((id: number) => {
    autoFocusMap.current.delete(id);
  });

  const focusNext = useMemoizedFn((selfID: number) => {
    // setTimeout to wait if an array new element to be added
    setTimeout(() => {
      const ids = Array.from(autoFocusMap.current.keys()).sort((a, b) => a - b);

      const index = ids.indexOf(selfID);

      if (index === -1) {
        return;
      }

      const nextID = ids.find(
        (key, i) =>
          i > index && autoFocusMap.current.get(key)?.canBeAutoFocused,
      );

      if (nextID == null) {
        return;
      }

      autoFocusMap.current.get(nextID)?.onFocus?.();
      autoFocusMap.current.get(selfID)?.onBlur?.();
    }, 10);
  });

  return (
    <AutoFocusContext.Provider
      value={{
        register,
        unregister,
        focusNext,
      }}
    >
      {children}
    </AutoFocusContext.Provider>
  );
};
